package com.bestvike.stone.spring.client;

import com.bestvike.stone.core.lang.StringUtils;
import com.bestvike.stone.spring.client.converter.FastJsonHttpMessageConverterEx;
import com.bestvike.stone.spring.client.converter.JacksonXmlHttpMessageConverterEx;
import com.bestvike.stone.spring.client.converter.StringHttpMessageConverterEx;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.http.MediaType;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.json.GsonHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by 许崇雷 on 2017-11-06.
 */
@Data
@ConfigurationProperties(prefix = "spring.http.converters")
public final class HttpConvertersProperties {
    private static final String PREFERRED_JSON_MAPPER_JACKSON = "jackson";
    private static final String PREFERRED_JSON_MAPPER_GSON = "gson";
    private static final String PREFERRED_JSON_MAPPER_FASTJSON = "fastjson";
    private static final String PREFERRED_XML_MAPPER_JACKSON = "jackson";
    private static final String PREFERRED_XML_MAPPER_JAXB = "jaxb";
    private static final List<HttpMessageConverter<?>> httpMessageConverters = new ArrayList<>();
    private static final List<HttpMessageConverter<?>> jsonMessageConverters = new ArrayList<>();
    private static final List<HttpMessageConverter<?>> xmlMessageConverters = new ArrayList<>();
    private String preferredJsonMapper;
    private String preferredXmlMapper;

    public void config(List<HttpMessageConverter<?>> converters) {
        if (converters == null)
            return;
        converters.clear();
        converters.addAll(this.getHttpConverters());
    }

    public void config(RestTemplateEx restTemplate) {
        switch (restTemplate.supportedType) {
            case JSON:
                restTemplate.setMessageConverters(this.getJsonConverters());
                break;
            case XML:
                restTemplate.setMessageConverters(this.getXmlConverters());
                break;
            default:
                throw new RuntimeException("Unexpected supportedType of RestTemplateEx");
        }
    }

    //获取数据转换器集合 Http
    private List<HttpMessageConverter<?>> getHttpConverters() {
        if (httpMessageConverters.isEmpty()) {
            httpMessageConverters.add(new ByteArrayHttpMessageConverter());
            httpMessageConverters.add(new StringHttpMessageConverterEx(MediaType.TEXT_PLAIN, false));
            httpMessageConverters.add(new ResourceHttpMessageConverter());
            httpMessageConverters.add(new SourceHttpMessageConverter());
            httpMessageConverters.add(new AllEncompassingFormHttpMessageConverter());
            httpMessageConverters.add(this.createJsonConverter());
            httpMessageConverters.add(this.createXmlConverter());
        }
        return httpMessageConverters;
    }

    //获取数据转换器集合 Json
    private List<HttpMessageConverter<?>> getJsonConverters() {
        if (jsonMessageConverters.isEmpty()) {
            jsonMessageConverters.add(new ByteArrayHttpMessageConverter());
            jsonMessageConverters.add(new StringHttpMessageConverterEx(MediaType.APPLICATION_JSON_UTF8, true));
            jsonMessageConverters.add(new ResourceHttpMessageConverter());
            jsonMessageConverters.add(new SourceHttpMessageConverter());
            jsonMessageConverters.add(new AllEncompassingFormHttpMessageConverter());
            jsonMessageConverters.add(this.createJsonConverter());
        }
        return jsonMessageConverters;
    }

    //获取数据转换器集合 Xml
    private List<HttpMessageConverter<?>> getXmlConverters() {
        if (xmlMessageConverters.isEmpty()) {
            xmlMessageConverters.add(new ByteArrayHttpMessageConverter());
            xmlMessageConverters.add(new StringHttpMessageConverterEx(MediaType.APPLICATION_XML, true));
            xmlMessageConverters.add(new ResourceHttpMessageConverter());
            xmlMessageConverters.add(new SourceHttpMessageConverter());
            xmlMessageConverters.add(new AllEncompassingFormHttpMessageConverter());
            xmlMessageConverters.add(this.createXmlConverter());
        }
        return xmlMessageConverters;
    }

    //创建数据转换器 Json
    private HttpMessageConverter<?> createJsonConverter() {
        String preferredJsonMapper = this.preferredJsonMapper == null ? StringUtils.EMPTY : this.preferredJsonMapper.toLowerCase();
        switch (preferredJsonMapper) {
            case PREFERRED_JSON_MAPPER_JACKSON:
                return new MappingJackson2HttpMessageConverter();
            case PREFERRED_JSON_MAPPER_GSON:
                return new GsonHttpMessageConverter();
            case PREFERRED_JSON_MAPPER_FASTJSON:
                return new FastJsonHttpMessageConverterEx();
            default:
                return new MappingJackson2HttpMessageConverter();
        }
    }

    //创建数据转换器 Xml
    private HttpMessageConverter<?> createXmlConverter() {
        String preferredXmlMapper = this.preferredXmlMapper == null ? StringUtils.EMPTY : this.preferredXmlMapper.toLowerCase();
        switch (preferredXmlMapper) {
            case PREFERRED_XML_MAPPER_JACKSON:
                return new JacksonXmlHttpMessageConverterEx();
            case PREFERRED_XML_MAPPER_JAXB:
                return new Jaxb2RootElementHttpMessageConverter();
            default:
                return new JacksonXmlHttpMessageConverterEx();
        }
    }
}
